package logic;
import java.util.ArrayList;
import java.util.Calendar;

import memory.GenericEvents;
import memory.Memory;

public class Find {
	public static ArrayList<GenericEvents> findResult;
	
	//@author A0096677H
	// Finds GenericEvents which occur on or across given date
	// Returns ArrayList of found GenericEvents
	public static ArrayList<GenericEvents> findDate(Calendar date, Memory memory) {
		assert date != null;
		findResult = new ArrayList<GenericEvents>();
		for (int i=0; i < memory.getSize(); i++) {
			Calendar start = memory.get(i).getStart();
			Calendar end = memory.get(i).getEnd();

			if (testTwoCalendar(date, start) || // Checks if given date is equals or between item's start and end date
					testTwoCalendar(date, end) ||
					(date.after(start) && date.before(end)) ) {
				findResult.add(memory.get(i));
			}
		}

		return findResult;
	}

	//@author A0096677H
	// Recursive method to narrow down search results by comparing different search terms
	public static ArrayList<GenericEvents> recursiveSearchTerms(String[] keywords, int index, ArrayList<GenericEvents> result) {
		ArrayList<GenericEvents> newResult = new ArrayList<GenericEvents>();
		if (index >= keywords.length) { // Base case: no more terms to search
			return result;
		} else { // Narrowing down results
			assert index < keywords.length;
			for (int i=0; i < result.size(); i++) {
				if (result.get(i).getName().contains(keywords[index])) { // Found term in name
					newResult.add(result.get(i));
				} else if ((result.get(i).getDescription()!= null) && result.get(i).getDescription().contains(keywords[index])) { // has description and found term in description
					newResult.add(result.get(i));
				}
			}
			return recursiveSearchTerms(keywords, index+1, newResult);
		}
	}

	//@author A0096677H
	// Only for delete and update direct commands to search for exact matching names
	// Should only return list of 1 item ideally
	public static ArrayList<GenericEvents> searchExact(String keyword, Memory memory) {
		assert keyword.length() != 0;
		ArrayList<GenericEvents> exactResult = new ArrayList<GenericEvents>();
		for (int i=0; i<memory.getSize(); i++) {
			containsKeyword(keyword, memory, exactResult, i);
		}
		return exactResult;
	}

	//@author A0096677H
	// Checks if memory item contains the keyword.
	// If contains, add to exactResult
	private static void containsKeyword(String keyword, Memory memory, ArrayList<GenericEvents> exactResult, int i) {
		if (memory.get(i).getName().equals(keyword)) { // found exact matching name item
			exactResult.add(memory.get(i));
		}
	}

	//@author A0096677H
	// Driver for recursive searching of array of keywords
	// Returns ArrayList of GenericEvents found containing keywords in their name or description
	public static ArrayList<GenericEvents> searchTerms(String[] keywords, Memory memory) {
		ArrayList<GenericEvents> result = new ArrayList<GenericEvents>(memory.getList());
		findResult = recursiveSearchTerms(keywords, 0, result); // calls recursive search to narrow down results
		if (findResult.size() == 0) { // no results
			System.out.println("No items found");
		} else if (findResult.size() == 1) { // one result, display item
			Display.displayDetailed(findResult.get(0));
		} else { // multiple results, display as list
			assert findResult.size() > 1;
			String title = formatSearchTitle(keywords);
			Display.displayList(findResult, title);
		}
		return findResult;
	}

	//@author A0096677H
	// Formats search title with keywords used to perform the search
	private static String formatSearchTitle(String[] keywords) {
		String title = "Search Keywords Result: " + keywords[0];
		for (int i=1; i<keywords.length; i++) {
			title += ", " + keywords[i];
		}
		return title;
	}

	//@author A0085082E
	// Returns true if two dates are the same
	private static boolean testTwoCalendar(Calendar a, Calendar b) {
		if (b == null) {
			return false;
		} else {
			assert (a != null) && (b != null);
			return (a.get(Calendar.YEAR)== b.get(Calendar.YEAR))&&
					(a.get(Calendar.MONTH) == b.get(Calendar.MONTH))&&
					(a.get(Calendar.DATE)== b.get(Calendar.DATE));
		}
	}

}
